package com.centaline.androidsalesblog.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;

import com.centaline.androidsalesblog.constants.AppConstant;
import com.centaline.androidsalesblog.model.businissobject.ModuleListBo;
import com.centaline.androidsalesblog.model.businissobject.NewGscopBo;
import com.centaline.androidsalesblog.model.businissobject.NewRegionBo;
import com.centaline.androidsalesblog.model.businissobject.SearchDataBo;
import com.centaline.androidsalesblog.model.databaseobject.BizGlobalDo;
import com.centaline.androidsalesblog.model.databaseobject.BizUnitDo;
import com.centaline.androidsalesblog.model.databaseobject.CityCenterDo;
import com.centaline.androidsalesblog.model.databaseobject.GscpDo;
import com.centaline.androidsalesblog.model.databaseobject.ModuleDo;
import com.centaline.androidsalesblog.model.databaseobject.NewRegionDo;
import com.centaline.androidsalesblog.model.databaseobject.RailLineDo;
import com.centaline.androidsalesblog.model.databaseobject.RailWayDo;
import com.centaline.androidsalesblog.model.databaseobject.RegionDo;
import com.centaline.androidsalesblog.model.databaseobject.SearchDataDo;
import com.centaline.androidsalesblog.model.responseobject.BizGlobalRo;
import com.centaline.androidsalesblog.model.responseobject.BizUnitRo;
import com.centaline.androidsalesblog.model.responseobject.MetroRo;
import com.centaline.androidsalesblog.model.responseobject.NewRegionRo;
import com.centaline.androidsalesblog.model.responseobject.PersonalizeRo;
import com.centaline.androidsalesblog.model.responseobject.RegionRo;
import com.centaline.androidsalesblog.model.responseobject.SearchDataRo;
import com.centaline.androidsalesblog.rx.request.RxRequest;
import com.orhanobut.logger.Logger;

import org.litepal.crud.DataSupport;

import java.util.ArrayList;
import java.util.List;

import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Func2;
import rx.functions.Func3;
import rx.functions.Func4;
import rx.functions.Func5;
import rx.schedulers.Schedulers;
import rx.subscriptions.CompositeSubscription;

/**
 * 基础数据service
 */
public class BaseDataService extends Service {

    private CompositeSubscription compositeSubscription = new CompositeSubscription();
    private BaseDataBinder baseDataBinder = new BaseDataBinder();
    private BaseDataUpdate localBaseDataUpdate = new BaseDataUpdate() {
        @Override
        public void update(int result) {
            if (baseDataUpdate != null) {
                baseDataUpdate.update(result);
            }
        }
    };
    private BaseDataUpdate baseDataUpdate;
    private String cityCode;

    @Override
    public IBinder onBind(Intent intent) {
        return baseDataBinder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        Logger.t("BaseDataService").d("onDestroy");
        compositeSubscription.unsubscribe();
        super.onDestroy();
    }

    /*请求全局配置信息*/
    private void requestBiz() {
        cityCode = AppConstant.CityCode;
        compositeSubscription.add(Observable.combineLatest(RxRequest.bizGlobal(BaseDataService.class),
                RxRequest.bizUnit(BaseDataService.class),
                new Func2<BizGlobalRo, BizUnitRo, Integer>() {
                    @Override
                    public Integer call(BizGlobalRo bizGlobalRo, BizUnitRo bizUnitRo) {
                        DataSupport.deleteAll(BizUnitDo.class, "cityCode = ?", cityCode);
                        DataSupport.deleteAll(CityCenterDo.class, "cityCode = ?", cityCode);
                        BizUnitDo bizUnitDo = bizUnitRo.getBizUnitDo();
                        CityCenterDo cityCenterDo = bizUnitDo.getCityCenterDo();
                        cityCenterDo.save();
                        bizUnitDo.save();
                        List<BizGlobalDo> bizGlobalDos = DataSupport.where("cityCode = ?", cityCode).find(BizGlobalDo.class);
                        BizGlobalDo bizGlobalDo = bizGlobalRo.getBizGlobalDo();
                        DataSupport.deleteAll(BizGlobalDo.class, "cityCode = ?", cityCode);
                        bizGlobalDo.setCityCode(cityCode);
                        bizGlobalDo.save();
                        int updateType = 0;
                        if (bizGlobalDos == null ||
                                bizGlobalDos.size() == 0 ||
                                !bizGlobalDo.getConfigVersion().equals(bizGlobalDos.get(0).getConfigVersion())) {
                            if (bizUnitDo.isEnableErshoufang() &&
                                    bizUnitDo.isEnableNewprop()) {//更新二手房新房
                                updateType = 1;
                            } else if (bizUnitDo.isEnableErshoufang()) {//更新二手房
                                updateType = 2;
                            } else if (bizUnitDo.isEnableNewprop()) {//更新新房
                                updateType = 3;
                            }
                            return updateType;
                        } else {
                            return updateType;
                        }
                    }
                }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Integer>() {
                    @Override
                    public void onCompleted() {
                        Logger.d("BaseDataService onCompleted");
                    }

                    @Override
                    public void onError(Throwable e) {
                        Logger.d("BaseDataService onError : %s", e.getMessage());
                        localBaseDataUpdate.update(UpdateResult.Error);
                        stopSelf();
                    }

                    @Override
                    public void onNext(Integer integer) {
                        switch (integer) {
                            case 1://更新二手新and房基础数据
                                requestAll();
                                break;
                            case 2://只更新二手基础数据
                                requestOnlySale();
                                break;
                            case 3://只更新新房基础数据
                                requestOnlyNew();
                                break;
                            default://不用更新基础数据
                                localBaseDataUpdate.update(UpdateResult.Keep);
                                stopSelf();
                                break;
                        }
                    }
                }));
    }

    /**
     * 包含二手新房模块
     */
    private void requestAll() {
        compositeSubscription.add(Observable.combineLatest(RxRequest.personalize(BaseDataService.class),
                RxRequest.region(BaseDataService.class),
                RxRequest.metro(BaseDataService.class),
                RxRequest.searchData(BaseDataService.class),
                RxRequest.newRegion(BaseDataService.class),
                new Func5<PersonalizeRo, RegionRo, MetroRo, SearchDataRo, NewRegionRo, Void>() {
                    @Override
                    public Void call(PersonalizeRo personalizeRo, RegionRo regionRo, MetroRo metroRo,
                                     SearchDataRo searchDataRo, NewRegionRo newRegionRo) {
                        savePersonalize(personalizeRo);
                        saveSaleRegion(regionRo);
                        saveMetro(metroRo);
                        saveSearchData(searchDataRo);
                        saveNewRegion(newRegionRo);
                        return null;
                    }
                }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Void>() {
                    @Override
                    public void onCompleted() {
                        Logger.d("onCompleted");
                    }

                    @Override
                    public void onError(Throwable e) {
                        localBaseDataUpdate.update(UpdateResult.Error);
                        stopSelf();
                    }

                    @Override
                    public void onNext(Void aVoid) {
                        Logger.d("onNext");
                        localBaseDataUpdate.update(UpdateResult.NewData);
                        stopSelf();
                    }
                }));
    }

    /**
     * 只有二手房模块
     */
    private void requestOnlySale() {
        compositeSubscription.add(Observable.combineLatest(RxRequest.personalize(BaseDataService.class),
                RxRequest.region(BaseDataService.class),
                RxRequest.metro(BaseDataService.class),
                RxRequest.searchData(BaseDataService.class),
                new Func4<PersonalizeRo, RegionRo, MetroRo, SearchDataRo, Void>() {
                    @Override
                    public Void call(PersonalizeRo personalizeRo, RegionRo regionRo, MetroRo metroRo,
                                     SearchDataRo searchDataRo) {
                        savePersonalize(personalizeRo);
                        saveSaleRegion(regionRo);
                        saveMetro(metroRo);
                        saveSearchData(searchDataRo);
                        return null;
                    }
                }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Void>() {
                    @Override
                    public void onCompleted() {
                        Logger.d("onCompleted");
                    }

                    @Override
                    public void onError(Throwable e) {
                        localBaseDataUpdate.update(UpdateResult.Error);
                        stopSelf();
                    }

                    @Override
                    public void onNext(Void aVoid) {
                        Logger.d("onNext");
                        localBaseDataUpdate.update(UpdateResult.NewData);
                        stopSelf();
                    }
                }));
    }

    /**
     * 只有新房模块
     */
    private void requestOnlyNew() {
        compositeSubscription.add(Observable.combineLatest(RxRequest.personalize(BaseDataService.class),
                RxRequest.searchData(BaseDataService.class),
                RxRequest.newRegion(BaseDataService.class),
                new Func3<PersonalizeRo, SearchDataRo, NewRegionRo, Void>() {
                    @Override
                    public Void call(PersonalizeRo personalizeRo, SearchDataRo searchDataRo, NewRegionRo newRegionRo) {
                        savePersonalize(personalizeRo);
                        saveSearchData(searchDataRo);
                        saveNewRegion(newRegionRo);
                        return null;
                    }
                }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Void>() {
                    @Override
                    public void onCompleted() {
                        Logger.d("onCompleted");
                    }

                    @Override
                    public void onError(Throwable e) {
                        localBaseDataUpdate.update(UpdateResult.Error);
                        stopSelf();
                    }

                    @Override
                    public void onNext(Void aVoid) {
                        Logger.d("onNext");
                        localBaseDataUpdate.update(UpdateResult.NewData);
                        stopSelf();
                    }
                }));
    }

    /**
     * 保存首页配置模块
     */
    private void savePersonalize(PersonalizeRo personalizeRo) {
        if (personalizeRo != null &&
                personalizeRo.getModuleBo() != null &&
                personalizeRo.getModuleBo().getModulesBo() != null &&
                personalizeRo.getModuleBo().getModulesBo().getModuleListBo() != null) {
            ArrayList<ModuleListBo> moduleListBos = personalizeRo.getModuleBo().getModulesBo().getModuleListBo();
            DataSupport.deleteAll(ModuleDo.class, "cityCode = ?", cityCode);
            for (ModuleListBo moduleListBo : moduleListBos) {
                DataSupport.saveAll(moduleListBo.getList());
            }
        }
    }

    /**
     * 保存搜索配置
     */
    private void saveSearchData(SearchDataRo searchDataRo) {
        if (searchDataRo != null) {
            DataSupport.deleteAll(SearchDataDo.class, "cityCode = ?", cityCode);
            ArrayList<SearchDataBo> searchDataBos = searchDataRo.getList();
            for (SearchDataBo searchDataBo : searchDataBos) {
                ArrayList<SearchDataDo> searchDataDos = searchDataBo.getSearchDataDos();
                for (SearchDataDo searchDataDo : searchDataDos) {
                    searchDataDo.setCityCode(cityCode);
                    searchDataDo.setName(searchDataBo.getName());
                }
                DataSupport.saveAll(searchDataDos);
            }
        }
    }

    /**
     * 保存二手房区域板块
     */
    private void saveSaleRegion(RegionRo regionRo) {
        if (regionRo != null) {
            DataSupport.deleteAll(RegionDo.class, "cityCode = ?", cityCode);
            DataSupport.deleteAll(GscpDo.class, "cityCode = ?", cityCode);
            ArrayList<RegionDo> regionDos = regionRo.getList();
            for (RegionDo regionDo : regionDos) {
                regionDo.setCityCode(cityCode);
                ArrayList<GscpDo> gscpDos = regionDo.getList();
                for (GscpDo gscpDo : gscpDos) {
                    gscpDo.setCityCode(cityCode);
                }
                DataSupport.saveAll(gscpDos);
            }
            DataSupport.saveAll(regionDos);
        }
    }

    /**
     * 保存地铁信息
     */
    private void saveMetro(MetroRo metroRo) {
        if (metroRo != null) {
            DataSupport.deleteAll(RailLineDo.class, "cityCode = ?", cityCode);
            DataSupport.deleteAll(RailWayDo.class, "cityCode = ?", cityCode);
            ArrayList<RailLineDo> railLineDos = metroRo.getList();
            for (RailLineDo railLineDo : railLineDos) {
                railLineDo.setCityCode(cityCode);
                ArrayList<RailWayDo> railWayDos = railLineDo.getList();
                for (RailWayDo railWayDo : railWayDos) {
                    railWayDo.setCityCode(cityCode);
                    railWayDo.setRailLineID(railLineDo.getRailLineID());
                }
                DataSupport.saveAll(railWayDos);
            }
            DataSupport.saveAll(railLineDos);
        }
    }

    /**
     * 保存新房区域板块
     */
    private void saveNewRegion(NewRegionRo newRegionRo) {
        if (newRegionRo != null) {
            DataSupport.deleteAll(NewRegionDo.class, "cityCode = ?", cityCode);
            ArrayList<NewRegionBo> newRegionBos = newRegionRo.getList();
            for (NewRegionBo newRegionBo : newRegionBos) {
                ArrayList<NewGscopBo> newGscopBos = newRegionBo.getList();
                for (NewGscopBo newGscopBo : newGscopBos) {
                    newGscopBo.getNewRegionDo().setCityCode(cityCode);
                    newGscopBo.getNewRegionDo().setNewPropCount(newGscopBo.getNewPropCount());
                    newGscopBo.getNewRegionDo().save();
                }
                newRegionBo.getNewRegionDo().setCityCode(cityCode);
                newRegionBo.getNewRegionDo().setNewPropCount(newRegionBo.getNewPropCount());
                newRegionBo.getNewRegionDo().save();
            }
        }
    }

    public class BaseDataBinder extends Binder {

        public void start(BaseDataUpdate update) {
            baseDataUpdate = update;
            requestBiz();
        }
    }

    /**
     * 更新结果
     */
    public interface UpdateResult {
        /**
         * 接口请求错误
         */
        int Error = -1;
        /**
         * 有新数据,需要更新UI
         */
        int NewData = 0;
        /**
         * 保持现状
         */
        int Keep = 1;
    }

    /**
     * 基础数据更新
     */
    public interface BaseDataUpdate {
        /**
         * {@link UpdateResult}
         *
         * @see UpdateResult
         */
        void update(int result);
    }
}
